package com.evolve.autotest.resulthandler.html;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.log4j.Logger;

import com.evolve.autotest.IResultHandler;
import com.evolve.autotest.Test;
import com.evolve.autotest.TestSuite;
import com.evolve.autotest.util.FileUtil;

/**
 * The HTML Output Handler will output the test result in a HTML
 * file format. 
 * @author qbacfre
 *
 */
public class HTMLResultHandler implements IResultHandler {
	
	private static final String TEST_CASE_RESULT = "<%= TEST_CASE.RESULT %>";

	private static final String TEST_CASE_NAME = "<%= TEST_CASE.NAME %>";

	private static final String TEST_SUITE_RESULT = "<%= TEST_SUITE.RESULT %>";

	private static final String TEST_SUITE_NAME = "<%= TEST_SUITE.NAME %>";

	private static final String TEST_SUITE_END = "<% TEST_SUITE_END %>";
	
	private static final String TEST_CASE_END = "<% TEST_CASE_END %>";
	
	private static final String TEST_CASE = "<% TEST_CASE %>";

	private static final String TEST_SUITE = "<% TEST_SUITE %>";

	private static final Logger logger = Logger.getLogger(HTMLResultHandler.class.getName());
	
	private File file;
	private File outputDirectory;

	/**
	 * Writes the result to HTML file
	 */
	public void handleResult(List<TestSuite> testCollection) {
		
		logger.info("Creating HTML output");
		
		String htmlTemplate = readHtmlTemplate();
		
		if (htmlTemplate != null) {
			String testSuiteContent = getTestSuiteContent(htmlTemplate);
			
			if (testSuiteContent != null) {
				String testContent = getTestContent(testSuiteContent);
				
				String content = replaceContent(testSuiteContent, testContent, testCollection);
				
				String output = htmlTemplate.replace(testSuiteContent, content);
				
				output = output.replaceAll(TEST_CASE_RESULT, "");
				output = output.replaceAll(TEST_CASE_NAME, "");
				output = output.replaceAll(TEST_SUITE_RESULT, "");
				output = output.replaceAll(TEST_SUITE_NAME, "");
				output = output.replaceAll(TEST_SUITE_END, "");
				output = output.replaceAll(TEST_CASE_END, "");
				output = output.replaceAll(TEST_CASE, "");
				output = output.replaceAll(TEST_SUITE, "");				
				
				writeOutput(output, outputDirectory);
			}
		} 
		
		logger.info("Creating HTML output finished");
	}

	/**
	 * This will create the index file out of the template file
	 * @param htmlTemplate
	 * @param testCollection
	 */
	private String getTestSuiteContent(String htmlTemplate) {
		
		String result = null;
		
		if (htmlTemplate.contains(TEST_SUITE)) {
						
			int index = htmlTemplate.indexOf(TEST_SUITE);
		
			String testSuiteContent = htmlTemplate.substring(index + TEST_SUITE.length(), htmlTemplate.length()); 
			
			if (testSuiteContent.contains(TEST_SUITE_END)) {
			
				int endIndex = testSuiteContent.indexOf(TEST_SUITE_END);
				
				result = testSuiteContent.substring(0, endIndex);
				
			} else {
				logger.error("Unable to find end tag for test suite");
			}
		} else {
			logger.error("Unable to find start tag for test suite");
		}
		
		return result;
	}
	
	
	private String getTestContent(String testContent) {
		
		String result = null;
		
		if (testContent.contains(TEST_CASE)) {
			
			int index = testContent.indexOf(TEST_CASE);
			
			if (testContent.contains(TEST_CASE_END)) {
				
				int endIndex = testContent.indexOf(TEST_CASE_END);
				
				result = testContent.substring(index + TEST_CASE.length(), endIndex);
								
			} else {
				logger.error("Unable to find end tag for test case");
			}
		} else {
			logger.error("Unable to find test case start tag");
		}
		
		return result;
	}

	
	/**
	 * @param testSuiteContent
	 * @param testContent 
	 * @param testCollection
	 * @return
	 */
	private String replaceContent(String testSuiteContent, String testContent, List<TestSuite> testCollection) {
		
		StringBuffer result = new StringBuffer();
		
		String tempResult;
		String tempTestResult;
		for (TestSuite suite : testCollection) {

			tempResult = testSuiteContent;
			
			tempResult = tempResult.replace(TEST_SUITE_NAME, suite.getName());
			
			tempResult = tempResult.replaceAll(TEST_SUITE_RESULT, suite.getSuiteReturnValue().toString());
			
			tempTestResult = replaceTestContent(testContent, suite.getTests());
			
			tempResult = tempResult.replace(testContent, tempTestResult);
			
			result.append(tempResult);
			
			tempResult = testSuiteContent;
		}
		
		return result.toString();
	}

	private String replaceTestContent(String testCaseContent, List<Test> tests) {
		
		StringBuffer result = new StringBuffer();
		
		String tempResult;
		
		for (Test test : tests) {
			
			tempResult = testCaseContent;
			
			tempResult = tempResult.replaceAll(TEST_CASE_NAME, test.getName());
			tempResult = tempResult.replaceAll(TEST_CASE_RESULT, test.getTestResult().toString());
			
			result.append(tempResult);
		}
		
		return result.toString();
	}

	/**
	 * Read the entire template file content
	 * @return
	 */
	private String readHtmlTemplate() {
		
		try {
			String content = FileUtil.readFileContent(file);
			return content;
		} catch (IOException e) {
			logger.error("Unable to read html template file " + file, e);
		}
		
		return null;
	}
	
	/**
	 * Writes the output to file
	 * @param output
	 * @param outputDirectory
	 */
	private void writeOutput(String output, File outDir) {

		try {
			FileUtil.writeOutput(output, new File(outDir.getAbsolutePath() + "/index.html"));
		} catch (IOException e) {
			logger.error("Unable to write output to index.html", e);
		} 
	}

	/**
	 * Sets the HTML template file
	 * @param file
	 */
	public void setTemplateFile(File file) {
		if (file == null) {
			throw new IllegalArgumentException("file cannot be null");
		}
		
		this.file = file;
	}

	/**
	 * Set the output directory
	 * @param outputDirectory
	 */
	public void setOutputDirectory(String outputDirectory) {
		if (outputDirectory == null) {
			throw new IllegalArgumentException("output directory cannot be null");
		}
		
		this.outputDirectory = new File(outputDirectory);
	}
}
